﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
using System.Data;
using System.ComponentModel;
using System.Windows.Controls.Primitives;
using System.Diagnostics;
using System.IO;
using DoubleH.Utility.Configuration;
using DoubleH.Utility.IO;
using FCNS.Data;
using System.Windows.Threading;
using System.Net;
using FSLib.IPMessager;
using FSLib.IPMessager.Entity;
using Table = FCNS.Data.Table;
using System.Net.NetworkInformation;
using System.Net.Sockets;

namespace DoubleH.Utility.Net
{
    public class NetUtility
    {
        /// <summary>
        /// 检测数据库服务器是否连接成功
        /// </summary>
        /// <param name="dc"></param>
        /// <returns></returns>
        public static bool TestConnection(DataConfig dc)
        {
            switch (dc.DataType)
            {
                case "MSSQL": return Net.NetUtility.TestConnection(dc.DataAddress, dc.Port, dc.TimeOut);
                default: return true;
            }
        }
        /// <summary>  
        /// 采用Socket方式，测试服务器连接  
        /// </summary>  
        /// <param name="host">服务器主机名或IP</param>  
        /// <param name="port">端口号</param>  
        /// <param name="millisecondsTimeout">等待时间：毫秒</param>  
        /// <returns></returns>  
        public static bool TestConnection(string host, int port, int millisecondsTimeout)
        {
            TcpClient client = new TcpClient();
            try
            {
                var ar = client.BeginConnect(host, port, null, null);
                ar.AsyncWaitHandle.WaitOne(millisecondsTimeout);
                return client.Connected;
            }
            catch
            {
                return false;
            }
            finally
            {
                client.Close();
            }
        }  

        /// <summary>
        /// 用于检查IP地址或域名是否可以使用TCP/IP协议访问(使用Ping命令),true表示Ping成功,false表示Ping失败 
        /// </summary>
        /// <param name="strIpOrDName">输入参数,表示IP地址或域名</param>
        /// <returns></returns>
        public static bool PingIpOrDomainName(string ipOrName, int timeOut = 5)
        {
            try
            {
                Ping objPingSender = new Ping();
                PingOptions objPinOptions = new PingOptions();
                objPinOptions.DontFragment = true;
                string data = "";
                byte[] buffer = Encoding.UTF8.GetBytes(data);
                int intTimeout = timeOut;
                PingReply objPinReply = objPingSender.Send(ipOrName, intTimeout, buffer, objPinOptions);
                string strInfo = objPinReply.Status.ToString();
                if (strInfo == "Success")
                {
                    return true;
                }
                else
                {
                    return false;
                }
            }
            catch (Exception)
            {
                return false;
            }
        }
        /// <summary>
        /// 获取指定ip的所在地址段的广播地址
        /// </summary>
        /// <param name="ipAddress"></param>
        /// <param name="subnetMask"></param>
        /// <returns></returns>
        public static IPAddress GetBroadcast(string ipAddress, string subnetMask)
        {
            try
            {
                byte[] ip = IPAddress.Parse(ipAddress).GetAddressBytes();
                byte[] sub = IPAddress.Parse(subnetMask).GetAddressBytes();

                // 广播地址=子网按位求反 再 或IP地址 
                for (int i = 0; i < ip.Length; i++)
                    ip[i] = (byte)((~sub[i]) | ip[i]);

                return new IPAddress(ip);
            }
            catch { return null; }
        }

        static IPMClient lanClient = null;
        public static IPMClient LanClient
        {
            get { return lanClient; }
        }

        static Host serverHost = null;
        public static Host ServerHost
        {
            get { return serverHost; }
        }

        static List<Host> allHostButMe = new List<Host>();
        public static List<Host> AllHostButMe
        {
            get { return allHostButMe; }
        }

        /// <summary>
        /// 用户登录后，必须调用它启用网络连接
        /// </summary>
        public static void StartNet()
        {
            if (lanClient != null && lanClient.IsInitialized)
            {
                //如果已经登录了只是注销状态
                lanClient.Config.NickName = Table.UserS.LoginUser.Name;
                lanClient.Config.GroupName = Table.UserS.LoginUser._GroupSName;
                lanClient.Online();
            }
            else
            {
                IPAddress[] allIP = Dns.GetHostAddresses(Dns.GetHostName());
                if (allIP == null)
                    return;

                IPAddress ip = IPAddress.Loopback;
                IPAddress.TryParse(DoubleHConfig.AppConfig.LocalIP, out ip);

                if (!allIP.Contains(ip))//如果不这样，当ip地址改变时运行就会报错
                    ip = IPAddress.Loopback;

                try
                {
                    lanClient = new FSLib.IPMessager.IPMClient(DoubleHConfig.AppConfig.ServerPort, Table.UserS.LoginUser.Name, Table.UserS.LoginUser._GroupSName, ip);
                }
                catch
                {
                    MessageWindow.Show("host 文件异常，请清空文件再重试.");
                    lanClient = null;
                }
                if (lanClient.IsInitialized)
                {
                    lanClient.OnlineHost.HostOnline += (ss, ee) => OnlineHost(ee);
                    lanClient.OnlineHost.HostOffline += (ss, ee) => OfflineHost(ee);
                    lanClient.Online();
                }
                else
                    lanClient.Dispose();
            }
        }

        /// <summary>
        /// 软件关闭前，必须调用它释放资源
        /// </summary>
        public static void CloseNet()
        {
            lanClient.OffLine();
            lanClient.Dispose();
            lanClient = null;
        }

        private static void OnlineHost(FSLib.IPMessager.Entity.OnlineHost.HostEventArgs e)
        {
            if (e.Host.NickName == "DoubleH Server")
                serverHost = e.Host;
            else
                allHostButMe.Add(e.Host);
        }

        private static void OfflineHost(FSLib.IPMessager.Entity.OnlineHost.HostEventArgs e)
        {
            if (e.Host.NickName == "DoubleH Server")
                serverHost = null;
            else
                allHostButMe.Remove(e.Host);
        }

        private static Dictionary<string, long> BuildExtendMessage(string fileName)
        {
            Dictionary<string, long> sizeDefine = new Dictionary<string, long>();
            System.IO.FileInfo fileInfo = new System.IO.FileInfo(fileName);
            if (fileInfo.Length != 0)
                sizeDefine.Add(fileName, fileInfo.Length);

            return sizeDefine;
        }

        /// <summary>
        /// 获取指定文件夹中的文件,服务器模式请通过事件获取，这里只会返回SqLite模式的文件列表
        /// </summary>
        /// <param name="fullDicName">FCNS.Data.DbDefine.dataDir 里面的完成目录名</param>
        /// <returns></returns>
        public static string[] GetFiles(string fullDicName )
        {
            switch (FCNS.Data.SQLdata.SqlConfig.DataType)
            {
                case DataType.MSSQL:
                    GetFilesOnServer(fullDicName);
                    return null;

                default: return GetFilesOnLocal(fullDicName);
            }
        }

        public static bool RemoveFile(string remoteFullFileName)
        {
            switch (FCNS.Data.SQLdata.SqlConfig.DataType)
            {
                case DataType.MSSQL: return RemoveFileOnServer(remoteFullFileName);
                default: return RemoveFileOnLocal(remoteFullFileName);
            }
        }

        public static bool SaveFile(string fullFileName, string remoteDirectoryName, string remoteFileName)
        {
            switch (FCNS.Data.SQLdata.SqlConfig.DataType)
            {
                case DataType.MSSQL: return SaveFileToServer(fullFileName, remoteDirectoryName, remoteFileName);
                default: return SaveFileToLocal(fullFileName, remoteDirectoryName, remoteFileName);
            }
        }

        public static void GetFilesOnServer(string fullDicName)
        {
            if (serverHost == null || !lanClient.IsInitialized)
                return;

            lanClient.Commander.SendCommand(serverHost, FSLib.IPMessager.Define.Consts.Commands.GetDirFiles, 0, fullDicName, string.Empty);
        }

        private static bool RemoveFileOnServer(string remoteFullFileName)
        {
            if (serverHost == null ||  !lanClient.IsInitialized)
                return false;

            lanClient.Commander.SendCommand(serverHost, FSLib.IPMessager.Define.Consts.Commands.DelMsg, 0, remoteFullFileName, string.Empty);
            return true;
        }

        private static bool SaveFileToServer(string fullFileName, string remoteDirectoryName, string remoteFileName)
        {
            if (!File.Exists(fullFileName) ||serverHost==null|| !lanClient.IsInitialized)
                return false;

            lanClient.PerformSendFile(Helper.BuildTaskList(BuildExtendMessage(fullFileName)), remoteDirectoryName + "\\" + remoteFileName, false, false, serverHost);
            return true;
        }
       
        //移除SQLITE模式的本机或共享模式的文件
        public static string[] GetFilesOnLocal(string fullDicName)
        {
                return Directory.GetFiles(fullDicName); 
        }

        public static bool RemoveFileOnLocal(string remoteFullFileName)
        {
            try
            {
                File.Delete(remoteFullFileName);
                return true;
            }
            catch { return false; }//如果删除的是本机文件，这里会异常
        }

        private static bool SaveFileToLocal(string fullFileName, string remoteDirectoryName, string remoteFileName)
        {
            try
            {
                string dir = DbDefine.dataDir + remoteDirectoryName + "\\";
                if (!Directory.Exists(dir))
                    Directory.CreateDirectory(dir);

                File.Copy(fullFileName, dir + remoteFileName, true);
                return true;
            }
            catch { return false; }
        }
    }
}